home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / utility / dirsize.zip / DIRSIZE.C < prev    next >
C/C++ Source or Header  |  1994-01-30  |  5KB  |  206 lines

  1. /*
  2. ** DirSize
  3. ** by Flavio Stanchina
  4. ** Loc. Montevaccino n░ 39
  5. ** 38040 Trento (Italy)
  6. ** 2:333/408.9@fidonet.org
  7. **
  8. ** This program is freeware. See the docs for more informations.
  9. */
  10.  
  11. #include <exec/types.h>
  12. #include <exec/memory.h>
  13. #include <exec/execbase.h>
  14. #include <dos/dos.h>
  15. #include <dos/rdargs.h>
  16.  
  17. #include <clib/exec_protos.h>
  18. #include <clib/dos_protos.h>
  19.  
  20. #if defined(__SASC)
  21. #define _USEOLDEXEC_ // Don't use SysBase for exec.library calls
  22. #include <proto/exec.h>
  23. #include <proto/dos.h>
  24. #endif
  25.  
  26. #include "DirSize_rev.h"
  27.  
  28. /***** Structure for passing data to/from DirSize() ****/
  29. #define DSD_PAT_SIZE 256
  30.  
  31. struct DirSizeData {
  32.     LONG    Files, Dirs;
  33.     LONG    Bytes, Blocks;
  34.  
  35.     TEXT    Pattern[DSD_PAT_SIZE];
  36.     LONG    BlockSize; // Data for GetDirSize
  37.     LONG    Extension;
  38.     LONG    DoAll; // Flags
  39.     LONG    DoLinks;
  40. };
  41.  
  42. static LONG GetDirSize(STRPTR, struct DirSizeData *);
  43.  
  44. /***** Libraries *****/
  45. struct DosLibrary    *DOSBase;
  46. TEXT                    DOSName[] = DOSNAME;
  47.  
  48. /***** Strings *****/
  49. TEXT Header[]    = "DirSize" VERSTAG " by Flavio Stanchina";
  50. TEXT FormatStr[] = "%ld files - %ld dirs - %ld bytes - %ld blocks\n";
  51. TEXT Template[]  = "DIR,P=PATTERN,BS=BLOCKSIZE/N,EXT=EXTENSION/N,ALL/S,LINKS/S";
  52.  
  53. enum ARG_INDEX { ARG_DIR, ARG_PAT, ARG_BS, ARG_EXT, ARG_ALL, ARG_LNK, ARG_COUNT };
  54.  
  55. /***** Program entry point (no startup code) *****/
  56. LONG __saveds Main(void)
  57. {
  58.     struct DirSizeData *dsd;
  59.     struct RDArgs *rda;
  60.     APTR args[ARG_COUNT];
  61.     LONG rc = RETURN_FAIL; // let's be pessimistic
  62.  
  63.     if(DOSBase = (struct DosLibrary *)OpenLibrary(DOSName, 37))
  64.     {
  65.         if(dsd = AllocMem(sizeof(struct DirSizeData), MEMF_CLEAR))
  66.         {
  67.             rc = RETURN_ERROR; // things are getting better
  68.  
  69. /*
  70. ** Just a quick note on the following assignment...
  71. **
  72. ** We're telling ReadArgs that our default directory is the current one, and
  73. ** the way to do that is making the argument point to an empty string. You
  74. ** might think that a null pointer would do, and you are half right, because
  75. ** location zero always contains zero (except if you own some bugged versions
  76. ** of the A590/A2091 ROMs), so the string starting at location zero can be
  77. ** thought of as an empty string.
  78. **
  79. ** But if you were running _The Enforcer_, it would report a read hit on
  80. ** location zero, so we supply our own empty string to settle the question
  81. ** once and for all.
  82. */
  83.  
  84.             args[ARG_DIR] = ""; // Means "current directory"
  85.             args[ARG_PAT] = NULL;
  86.             args[ARG_BS ] = NULL;
  87.             args[ARG_EXT] = NULL;
  88.             args[ARG_ALL] = FALSE;
  89.             args[ARG_LNK] = FALSE;
  90.  
  91.             if(rda = ReadArgs(Template, (LONG *)args, NULL))
  92.             {
  93.                 if(args[ARG_PAT])
  94.                     if(ParsePatternNoCase((STRPTR)args[ARG_PAT], dsd->Pattern, DSD_PAT_SIZE) <= 0)
  95.                     {
  96.                         PutStr("Ignoring wrong pattern\n");
  97.                         dsd->Pattern[0] = '\0';
  98.                     }
  99.  
  100.                 dsd->BlockSize = args[ARG_BS ] ? *(LONG *)args[ARG_BS ] : 512;
  101.                 dsd->Extension = args[ARG_EXT] ? *(LONG *)args[ARG_EXT] : 72;
  102.                 dsd->DoAll     = (LONG)args[ARG_ALL];
  103.                 dsd->DoLinks   = (LONG)args[ARG_LNK];
  104.  
  105.                 if((dsd->BlockSize >= 8) || (dsd->Extension >= 0))
  106.                 {
  107.                     LONG result2;
  108.  
  109.                     if(result2 = GetDirSize((STRPTR)args[ARG_DIR], dsd))
  110.                     {
  111.                         PrintFault(result2, Header);
  112.                         rc = RETURN_WARN;
  113.                     }
  114.                     else rc = RETURN_OK; // we're lucky today
  115.  
  116.                     VPrintf(FormatStr, (LONG *)dsd);
  117.                 }
  118.                 else PrintFault(ERROR_BAD_NUMBER, Header);
  119.  
  120.                 FreeArgs(rda);
  121.             }
  122.             else PrintFault(IoErr(), Header);
  123.  
  124.             FreeMem(dsd, sizeof(struct DirSizeData));
  125.         }
  126.         else PrintFault(ERROR_NO_FREE_STORE, Header);
  127.  
  128.         CloseLibrary((struct Library *)DOSBase);
  129.     }
  130.  
  131.     return(rc);
  132. }
  133.  
  134. /***** Reads the directory *****/
  135. // Returns zero if ok, or DOS error code if something went wrong.
  136. static LONG GetDirSize(STRPTR name, struct DirSizeData *dsd)
  137. {
  138.     BPTR lock, oldCD;
  139.     struct FileInfoBlock *fib;
  140.     LONG temp;
  141.     LONG rc;
  142.  
  143.     /* Set up some things */
  144.     if(fib = AllocDosObject(DOS_FIB, NULL))
  145.     {
  146.         if(lock = Lock(name, ACCESS_READ))
  147.         {
  148.             oldCD = CurrentDir(lock);
  149.  
  150.             if(Examine(lock, fib))
  151.             {
  152.                 while(ExNext(lock, fib))
  153.                 {
  154.                     if(fib->fib_DirEntryType < 0) // It's a file...
  155.                     {
  156.                         /* Let's see if this file is to be included... */
  157.                         if(dsd->Pattern[0])
  158.                             if(!MatchPatternNoCase(dsd->Pattern, fib->fib_FileName))
  159.                             {
  160.                                 if(IoErr() == ERROR_TOO_MANY_LEVELS) break;
  161.                                 else continue;
  162.                             }
  163.  
  164.                         /* Update our counts */
  165.                         dsd->Files += 1;
  166.                         if((fib->fib_DirEntryType != ST_LINKFILE) || dsd->DoLinks)
  167.                         {
  168.                             dsd->Bytes += fib->fib_Size;
  169.                             if(fib->fib_Size)
  170.                             {
  171.                                 // Data blocks
  172.                                 temp = (fib->fib_Size + dsd->BlockSize - 1) / dsd->BlockSize;
  173.  
  174.                                 if(dsd->Extension)
  175.                                     // Header + extension blocks
  176.                                     temp += (temp + dsd->Extension - 1) / dsd->Extension;
  177.                             }
  178.                             else temp = 1; // A zero length file requires an header
  179.                             dsd->Blocks += temp;
  180.                         }
  181.                         else dsd->Blocks += 1;
  182.                     } else {
  183.                         dsd->Dirs += 1;
  184.                         dsd->Blocks += 1;
  185.  
  186.                         if(dsd->DoAll && ((fib->fib_DirEntryType != ST_LINKDIR) || dsd->DoLinks))
  187.                             if(rc = GetDirSize(fib->fib_FileName, dsd)) goto error;
  188.                     }
  189.                 }
  190.  
  191.                 if((rc = IoErr()) == ERROR_NO_MORE_ENTRIES) rc = 0;
  192.             }
  193.             else rc = IoErr();
  194. error:
  195.             CurrentDir(oldCD);
  196.             UnLock(lock);
  197.         }
  198.         else rc = IoErr();
  199.  
  200.         FreeDosObject(DOS_FIB, fib);
  201.     }
  202.     else rc = ERROR_NO_FREE_STORE;
  203.  
  204.     return(rc);
  205. }
  206.